/*
 * ============================================================================
 *                   GNU Lesser General Public License
 * ============================================================================
 *
 *
 *
 * 
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 * 
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307, USA.
 * 
 *
 *
 */
package rad.framework.security.encryption;

import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.KeySpec;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.PBEParameterSpec;

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

/**
 * A DES implementation that uses a pass phrase as the key.
 * 
 * The pass phrase is set using the following system property:
 * rad.framework.security.encryption.DesPassPhraseEncryptor.passphrase
 * 
 * @author boudyacho
 * 
 */
public class DesPassPhraseEncryptor implements Encryptor {

	public static final String PASS_PHRASE_PROPERTY_NAME = "rad.framework.security.encryption.DesPassPhraseEncryptor.passphrase";

	private Cipher ecipher;

	private Cipher dcipher;

	// 8-byte Salt
	private static final byte[] SALT = { (byte) 0xA9, (byte) 0x9B, (byte) 0xC8,
			(byte) 0x32, (byte) 0x56, (byte) 0x35, (byte) 0xE3, (byte) 0x03 };

	private int iterationCount = 19;

	public DesPassPhraseEncryptor() {
		try {
			String passPhrase = System.getProperty(PASS_PHRASE_PROPERTY_NAME);
			if (passPhrase == null) {
				throw new RuntimeException(PASS_PHRASE_PROPERTY_NAME
						+ " system property must be set.");
			}

			// Create the key
			KeySpec keySpec = new PBEKeySpec(passPhrase.toCharArray(), SALT,
					iterationCount);
			SecretKey key = SecretKeyFactory.getInstance("PBEWithMD5AndDES")
					.generateSecret(keySpec);
			ecipher = Cipher.getInstance(key.getAlgorithm());
			dcipher = Cipher.getInstance(key.getAlgorithm());

			// Prepare the parameter to the ciphers
			AlgorithmParameterSpec paramSpec = new PBEParameterSpec(SALT,
					iterationCount);

			// Create the ciphers
			ecipher.init(Cipher.ENCRYPT_MODE, key, paramSpec);
			dcipher.init(Cipher.DECRYPT_MODE, key, paramSpec);
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	public String encrypt(String s) {
		try {
			byte[] utf8 = s.getBytes("UTF8");
			byte[] enc = ecipher.doFinal(utf8);
			return new BASE64Encoder().encode(enc);
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	public String decrypt(String s) {
		try {
			byte[] dec = new BASE64Decoder().decodeBuffer(s);
			byte[] utf8 = dcipher.doFinal(dec);
			return new String(utf8, "UTF8");
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}
}
